﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using LowLevelGraphics.Extractors;

using LowLevelGraphics;
using LowLevelGraphics.Filter;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// BW2 = bwselect(BW,n) displays the image BW on the screen and 
    /// lets you select the (r,c) coordinates using the mouse.
    /// If you omit BW, bwselect operates on the image in the current axes.
    /// Use normal button clicks to add points. 
    /// Pressing Backspace or Delete removes the previously selected point. 
    /// A shift-click, right-click, or double-click selects the final point; 
    /// pressing Return finishes the selection without adding a point.
    /// 
    /// [BW2,idx] = bwselect(...) returns the linear indices of the pixels belonging to the selected objects.
    /// 
    /// BW2 = bwselect(x,y,BW,xi,yi,n) uses the vectors x and y to establish a nondefault spatial coordinate system for BW1. xi and yi are scalars or equal-length vectors that specify locations in this coordinate system.
    /// 
    /// [x,y,BW2,idx,xi,yi] = bwselect(...) returns the XData and YData in x and y, the output image in BW2, linear indices of all the pixels belonging to the selected objects in idx, and the specified spatial coordinates in xi and yi.
    /// 
    /// If bwselect is called with no output arguments, the resulting image is displayed in a new figure.    /// </summary>
    public class bwselect : BaseForeBackgroundColorFilter
    {
        protected Point[] m_aPoint = null;
        protected List<Blob> m_aBlob = new List<Blob>();
        /// <summary>
        /// Default constructor
        /// </summary>
        public bwselect()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_aPoint"></param>
        public bwselect(Point[] _aPoint)
        {
            m_aPoint = _aPoint;
        }

        /// <summary>
        /// used by cloning this instance
        /// </summary>
        /// <param name="_bwselect"></param>
        internal bwselect(bwselect _bwselect)
        {
        }

        /// <summary>
        /// Executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmapSelectObject = (UnsafeBitmap)_bitmap.Clone();
            BlobExtractor blobExtractor = new BlobExtractor(bitmapSelectObject);
            _bitmap.Clear();
            Blob[] aBlob = blobExtractor.Detect();
            if (aBlob.Length == 1 && Math.Abs(aBlob[0].Points.Count - _bitmap.Width * _bitmap.Height) < 2)
            {
                Debug.WriteLine("There might be an error!");
            }
            foreach (Point point in m_aPoint)
            {
                foreach (Blob blob in aBlob)
                {
                    m_aBlob.Add(blob);
                    if (blob == null) continue; //this shouldn't happen normally...
                    bool bContains = blob.Points.Contains(point);
                    if (bContains)
                    {
                        foreach (Point pointBlob in blob.Points)
                        {
                            _bitmap.SetPixel(pointBlob.X, pointBlob.Y, m_ColorForeground);
                        }
                    }
                }
            }
            bitmapSelectObject.Dispose();
            return _bitmap;
        }

        /// <summary>
        /// Clones this instance
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new bwselect(this);
        }
    }
}
